package com.example.widget_lib.widget.touch;

import com.example.widget_lib.ResourceTable;
import com.example.widget_lib.utils.LogUtil;
import com.example.widget_lib.utils.PxUtil;
import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorProperty;
import ohos.agp.animation.AnimatorValue;
import ohos.agp.components.*;
import ohos.agp.components.element.Element;
import ohos.agp.components.element.FrameAnimationElement;
import ohos.agp.components.element.PixelMapElement;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.render.PixelMapHolder;
import ohos.agp.utils.Color;
import ohos.agp.utils.Point;
import ohos.app.Context;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.global.resource.Resource;
import ohos.media.image.ImageSource;
import ohos.media.image.PixelMap;
import ohos.media.image.common.ImageInfo;
import ohos.multimodalinput.event.TouchEvent;

public class RefreshView extends StackLayout implements Component.DrawTask, Component.TouchEventListener, ComponentTreeObserver.ScrollChangedListener {
    private String TAG = this.getClass().getSimpleName();
    private Context mContext;
    private DependentLayout mTouchView;
    private Image mAnimList;
    private int mScreenW; // 屏幕分辨率
    private int mHeadW, mHeadH;// 头部笑脸的宽度，高度
    private int mDownY;
    private int mMoveY;
    private int mUpY; // 抬手时已滑动的高度值
    private int mRadius = 10;// 小圆点半径,默认为10
    private int mScrDistance = (int) PxUtil.vp2px(180); // 下滑最大高度
    private int mInitLeftPX, mInitRightPX;
    private int mBmpL, mBmpT; // 头部位图左上值
    private ScrollHelper mScroller; // 图片控件滚动器
    private ScrollHelper mScroller1; // 笑脸控件滚动器
    private Paint mPaint;
    private PixelMap mHeadBmp;
    private boolean isGonePoint;// 是否隐藏圆点,默认false
    private AnimatorProperty mTranslateAnim;
    private FrameAnimationElement mAniDraw;
    private boolean mAnimIsIng; // 动画是否进行中...
    private boolean notDraw = true;

    private EventHandler handler = new EventHandler(EventRunner.getMainEventRunner());

    public RefreshView(Context context) {
        this(context, null);
    }

    public RefreshView(Context context, AttrSet attrSet) {
        this(context, attrSet, null);
    }

    public RefreshView(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
        Component root = LayoutScatter.getInstance(context).parse(ResourceTable.Layout_pullrefresh_layout, this, false);
        mTouchView = (DependentLayout) root.findComponentById(ResourceTable.Id_id_touchImg);
        mAnimList = (Image) root.findComponentById(ResourceTable.Id_id_animList);
        addComponent(root);
        mAnimList.setVisibility(HIDE);

        init(context);
        addDrawTask(this::onDraw);
        setTouchEventListener(this::onTouchEvent);
        getComponentTreeObserver().addScrolledListener(this::onScrolled);
    }

    private void init(Context context) {
        mContext = context;
        mScreenW = PxUtil.screenWidth();
        try {
            Resource r = getResourceManager().getResource(ResourceTable.Media_load_more_1);
            ImageSource source = ImageSource.create(r, new ImageSource.SourceOptions());
            mHeadBmp = source.createPixelmap(new ImageSource.DecodingOptions());
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (mHeadBmp == null) {
            return;
        }
        ImageInfo headImageInfo = mHeadBmp.getImageInfo();

        mHeadW = headImageInfo.size.width;
        mHeadH = headImageInfo.size.height;
        mInitLeftPX = mScreenW / 2 - mHeadW;
        mInitRightPX = mScreenW / 2 + mHeadW;
        mBmpL = mScreenW / 2 - headImageInfo.size.width / 2;
        mBmpT = 0;

        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setDither(true);
        mPaint.setColor(Color.RED);
        mPaint.setStyle(Paint.Style.FILL_STYLE);
        mScroller = new ScrollHelper();
        mScroller1 = new ScrollHelper();
        initAnim(context);
    }

    private void initAnim(Context context) {
        mAniDraw = new FrameAnimationElement(context, ResourceTable.Graphic_animation_element);
        mAnimList.setBackground(mAniDraw);
        mAnimList.setWidth(mHeadW);
        mAnimList.setHeight(mHeadH);
    }


    @Override
    public void onDraw(Component component, Canvas canvas) {
        if (notDraw)
            return;
        // 绘制顶部两个圆点
        if (isGonePoint) {
            // 隐藏
            canvas.drawCircle(mInitLeftPX, 0, 0, mPaint);
            canvas.drawCircle(mInitRightPX, 0, 0, mPaint);
        } else {
            // 显示
            canvas.drawCircle(mInitLeftPX, 0, mRadius, mPaint);
            canvas.drawCircle(mInitRightPX, 0, mRadius, mPaint);
        }

        // 绘制头部图片
        PixelMapHolder holder = new PixelMapHolder(mHeadBmp);
        canvas.drawPixelMapHolder(holder, mBmpL, mBmpT, mPaint);
        // 绘制斜线
        Point startLeftPoint = new Point(mInitLeftPX, 0);
        Point endLeftPoint = new Point(mBmpL, mBmpT + mHeadH / 2);
        canvas.drawLine(startLeftPoint, endLeftPoint, mPaint);
        Point startRightPoint = new Point(mInitRightPX, 0);
        Point endRightPoint = new Point(mBmpL + mHeadW, mBmpT + mHeadH / 2);
        canvas.drawLine(startRightPoint, endRightPoint, mPaint);
    }

    @Override
    public boolean onTouchEvent(Component component, TouchEvent touchEvent) {
        if (mAnimIsIng) {
            return true;
        }
        isGonePoint = false;
        switch (touchEvent.getAction()) {
            case TouchEvent.PRIMARY_POINT_DOWN:
                notDraw = false;
                mDownY = (int) touchEvent.getPointerPosition(touchEvent.getIndex()).getY();
                LogUtil.loge(TAG, "mDownY:" + mDownY);
                return true;
            case TouchEvent.POINT_MOVE:
                mMoveY = (int) touchEvent.getPointerPosition(touchEvent.getIndex()).getY() - mDownY;

                if (mMoveY > mHeadH * 2) { // 如果下拉的距离大于2倍的控件高度，则让控件悬在外部控件的顶上
                    mBmpT = mMoveY - mHeadH;
                    //限制下拉距离
                    if (mMoveY > mScrDistance) {
                        mBmpT = mScrDistance - mHeadH;
                    }
                } else {
                    mBmpT = mMoveY - mMoveY / 2;
                }

                //同样外部控件也需要做下拉距离限制
                if (mMoveY > mScrDistance) {
                    mMoveY = mScrDistance;
                }
                mTouchView.setTranslationY(mMoveY);
                invalidate();
                break;
            case TouchEvent.PRIMARY_POINT_UP:
                mUpY = mBmpT;
                mRadius = 0;
                int bmpHeight = mHeadBmp.getImageInfo().size.height;
//                mScroller1.startScroll(0, mBmpT, 0, -mBmpT - bmpHeight);
                //ScrollerHelper功能不全，暂时使用AnimatorValue来实现渐变效果
                startAnimation(250, bmpHeight);
                break;
        }
        return true;
    }


    private void startAnimation(long duration, int bmpHeight) {
        AnimatorValue animatorValue = new AnimatorValue();
        int tempTop = mBmpT;
        animatorValue.setDuration(duration);
        animatorValue.setValueUpdateListener((animatorValue1, percent) -> {
            mBmpT = (int) (tempTop + ((-tempTop - bmpHeight) - tempTop) * percent);
            LogUtil.loge(TAG, "mBmpT:" + mBmpT);
            invalidate();
        });
        animatorValue.setStateChangedListener(new Animator.StateChangedListener() {
            @Override
            public void onStart(Animator animator) {

            }

            @Override
            public void onStop(Animator animator) {

            }

            @Override
            public void onCancel(Animator animator) {

            }

            @Override
            public void onEnd(Animator animator) {
                animatorValue.stop();
                startUpToDownAnim();
            }

            @Override
            public void onPause(Animator animator) {

            }

            @Override
            public void onResume(Animator animator) {

            }
        });
        animatorValue.start();
    }

    /**
     * 开始由上到下的动画
     */
    private void startUpToDownAnim() {
        mAnimIsIng = true;
        mAnimList.setVisibility(VISIBLE);
        mAnimList.setTranslationY(mUpY);
        mAniDraw.start();
        stopRefresh();

        //属性动画效果不好，会出现重复，暂停使用，直接赋值
        mTranslateAnim = new AnimatorProperty();
        mTranslateAnim.setStateChangedListener(new Animator.StateChangedListener() {
            @Override
            public void onStart(Animator animator) {
                LogUtil.loge(TAG, "动画开始...");
            }

            @Override
            public void onStop(Animator animator) {
            }

            @Override
            public void onCancel(Animator animator) {
            }

            @Override
            public void onEnd(Animator animator) {
                LogUtil.loge(TAG, "动画结束...mUpY:" + mUpY);
                mTranslateAnim.stop();
                //使用帧动画，实现硬币滚动效果
                mAniDraw.start();
                stopRefresh();
            }

            @Override
            public void onPause(Animator animator) {
            }

            @Override
            public void onResume(Animator animator) {
            }
        });

//        mTranslateAnim.moveFromY(0).moveToY(mUpY).setDuration(400).setLoopedCount(0).setTarget(mAnimList);
//        // 越来越快
//        mTranslateAnim.setCurveType(Animator.CurveType.ACCELERATE);
//        mTranslateAnim.start();
    }


    /**
     * 停止刷新动画
     */
    public void stopRefresh() {
        int time = 0;
        for (int i = 0; i < mAniDraw.getNumberOfFrames(); i++) {
            time += mAniDraw.getDuration(i); // 计算动画播放的时间
        }
        handler.postTask(() -> {
            LogUtil.loge(TAG, "stopRefresh");
            // 隐藏逐帧控件
            mAnimList.setVisibility(HIDE);
            // 注：结束后需要调用stop不然不能重复实现动画效果
            mAniDraw.stop();
            // 动画全部结束
            mAnimIsIng = false;
//            mScroller.startScroll(0, (int) mTouchView.getTranslationY(), 0, -(int) mTouchView.getTranslationY());
            isGonePoint = true;
            mUpY = 0;
            mDownY = 0;
            mMoveY = 0;
            mTouchView.setTranslationY(mMoveY);
            mRadius = 10;
            mBmpT = -mHeadBmp.getImageInfo().size.height;
            invalidate();
        }, time + 100);
    }

    @Override
    public void onScrolled() {
        // 先判断mScroller滚动是否完成
//        if (mScroller.isFinished()) {
//            mTouchView.setTranslationY(mScroller.getScrollDistanceY());
//            // 必须调用该方法，否则不一定能看到滚动效果
//            invalidate();
//        }
//
//        if (mScroller1.isFinished()) {
//            mBmpT = mScroller1.getScrollDistanceY();
//            // 必须调用该方法，否则不一定能看到滚动效果
//            invalidate();
//        }
    }


    @Override
    public void release() {
        super.release();
        if (mTranslateAnim != null) {
            mTranslateAnim.release();
        }
        if (mAniDraw != null) {
            mAniDraw.release();
        }
    }
}
